package cn.virens.common.mybatis.datasource.annotations.config;

import cn.virens.common.mybatis.datasource.annotations.handler.DynamicDataSourceAnnotationSource;
import cn.virens.common.mybatis.datasource.annotations.handler.DynamicDataSourceMethodInterceptor;
import cn.virens.common.mybatis.datasource.annotations.handler.DynamicDataSourceMethodPointcutAdvisor;
import cn.virens.common.spring.annotations.config.VirAbstractImportAware;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;

import java.lang.annotation.Annotation;

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class DynamicDataSourceConfiguration extends VirAbstractImportAware {

    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Bean("dynamicDataSourceAnnotationSource")
    public DynamicDataSourceAnnotationSource dynamicDataSourceAnnotationSource() throws Exception {
        return new DynamicDataSourceAnnotationSource();
    }

    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Bean("dynamicDataSourceMethodInterceptor")
    public DynamicDataSourceMethodInterceptor dynamicDataSourceMethodInterceptor(//
                                                                                 @Qualifier("dynamicDataSourceAnnotationSource") DynamicDataSourceAnnotationSource dynamicDataSourceAnnotationSource//
    ) throws Exception {
        DynamicDataSourceMethodInterceptor interceptor = new DynamicDataSourceMethodInterceptor();
        interceptor.setAnnotationSource(dynamicDataSourceAnnotationSource);

        return interceptor;
    }

    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @Bean("dynamicDataSourceMethodPointcutAdvisor")
    public DynamicDataSourceMethodPointcutAdvisor dynamicDataSourceMethodPointcutAdvisor(//
                                                                                         @Qualifier("dynamicDataSourceAnnotationSource") DynamicDataSourceAnnotationSource dynamicDataSourceAnnotationSource,//
                                                                                         @Qualifier("dynamicDataSourceMethodInterceptor") DynamicDataSourceMethodInterceptor dynamicDataSourceMethodInterceptor//
    ) throws Exception {
        DynamicDataSourceMethodPointcutAdvisor advisor = new DynamicDataSourceMethodPointcutAdvisor();
        advisor.setOrder(getInteger("order", Ordered.LOWEST_PRECEDENCE));
        advisor.setAnnotationSource(dynamicDataSourceAnnotationSource);
        advisor.setAdvice(dynamicDataSourceMethodInterceptor);

        return advisor;
    }

    @Override
    protected Class<? extends Annotation> getAnnotationClass() {
        return EnableDynamicDataSource.class;
    }

}
